package token

import (
	"github.com/gogf/gf/crypto/gmd5"
	"github.com/gogf/gf/frame/g"
	"github.com/gogf/gf/net/ghttp"
	"github.com/gogf/gf/util/gconv"
)

var platform = ""

func SetPlatform(p string) {
	platform = p
}

func GetPlatform() string {
	return platform
}

func getRedisKeyByPlatform(key string) string {
	return platform + ":" + key
}

func GenerateLoginToken(memberId int, realname string) (string, error) {
	tokenStringMd5 := gmd5.MustEncryptString(g.Cfg().GetString("jwt.sign", "gdshop") + gconv.String(memberId))
	g.Redis().Do("HSET", getRedisKeyByPlatform("VerifyLoginToken"), tokenStringMd5, memberId)

	if g.Cfg().GetBool("site.OnlyOneLogin", false) {
		// 只允许在一个地点登录
		g.Redis().Do("HSET", getRedisKeyByPlatform("VerifyLoginTokenMemberId"), memberId, tokenStringMd5)
		// 删除 VerifyLoginToken 里面多余的 数据
		verifyLoginTokens, _ := g.Redis().DoVar("HGETALL", getRedisKeyByPlatform("VerifyLoginToken"))
		// 使用批量操作
		conn := g.Redis().Conn()
		defer conn.Close()
		for key, value := range verifyLoginTokens.Map() {
			if gconv.String(value) == gconv.String(memberId) && tokenStringMd5 != key {
				// 使用批量操作
				conn.Send("HDEL", getRedisKeyByPlatform("VerifyLoginToken"), key)
			}
		}
		conn.Flush()
	}

	return tokenStringMd5, nil
}

func VerifyLoginToken(tokenString string) uint {
	if tokenString == "" {
		return 0
	}
	// 不为空，查缓存
	v, _ := g.Redis().DoVar("HGET", getRedisKeyByPlatform("VerifyLoginToken"), tokenString)
	if v != nil && v.String() != "" {
		// 是否只允许一个用户登录
		if g.Cfg().GetBool("site.OnlyOneLogin", false) {
			// 只允许在一个地点登录
			// 反查当前用户ID是否等于token
			memberToken, _ := g.Redis().DoVar("HGET", getRedisKeyByPlatform("VerifyLoginTokenMemberId"), v.Uint())
			if memberToken.IsNil() || memberToken.IsEmpty() {
				return 0
			}

			// 对比
			if memberToken.String() != tokenString {
				// 不相等，返回失败
				return 0
			} else {
				return v.Uint()
			}
		}
		return v.Uint()
	} else {
		return 0
	}
}

func Layout(memberId int, tokenString string) {
	if tokenString == "" {
		return
	}
	g.Redis().Do("HDEL", getRedisKeyByPlatform("VerifyLoginToken"), gmd5.MustEncryptString(tokenString))
	// 删除
	g.Redis().Do("HDEL", getRedisKeyByPlatform("VerifyLoginTokenMemberId"), memberId)
}

func GetLoginMemberId(r *ghttp.Request) int {
	return r.GetCtxVar("memberId", 0).Int()
}

func GetToken(r *ghttp.Request) string {
	token := r.Header.Get("token")
	return token
}

// 检测token
func CheckToken(r *ghttp.Request) bool {
	token := GetToken(r)
	if token == "" {
		return false
	}
	memberId := VerifyLoginToken(token)

	if memberId > 0 {
		// 写入全局上下文
		r.SetCtxVar("memberId", memberId)
		return true
	} else {
		// 如果是 0 说明是未登陆的
		return false
	}
}

// 检测权限，第一期不开放
func CheckPermissions(r *ghttp.Request) bool {
	return true
}
